
#include "stdio.h"
#include <ctype.h>
#include "los_base.h"
#include "los_task.ph"
#include "los_typedef.h"
#include "los_sys.h"
#include "bsp_api.h"
#include "stm32f4xx_hal_gpio.h"
#include "hardware_com.h"
#include "omip_log.h"

static int m_iDelayReboot =0; 	 //是否延时重启系统
static int m_iDelayResetWifi =0; //是否需要延时重启WIFI


void system_soft_reset() //关闭所有中断并复位
{
	__set_FAULTMASK(1);
	NVIC_SystemReset();
}

void system_reset_delay() //设置系统延时复位标志
{
	printf("system will be reset after 3s.\r\n");
	m_iDelayReboot =1;
}

int system_need_reset() //获取系统延时复位标志
{
	int iRet =m_iDelayReboot;
	m_iDelayReboot =0;
	return iRet;
}


void wifi_reset() //复位WIFI
{
    HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_RESET);
    LOS_TaskDelay(3000);
    HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_SET);
    OMIP_LOG_INFO("wifi pin is reset.\r\n");
    LOS_TaskDelay(5000);
}

//蓝牙复位
void ble_reset() 
{
    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
    LOS_TaskDelay(3000);
    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_SET);
    OMIP_LOG_INFO("ble pin is reset.\r\n");
    LOS_TaskDelay(5000);
}

void wifi_reset_delay() //设置WIFI延时复位标志
{
	m_iDelayResetWifi =1;
}

int	 wifi_need_reset() //获取WIFI延时复位标志
{
	int iRet =m_iDelayResetWifi;
	m_iDelayResetWifi =0;
	return iRet;
}

void led_wifi_on() //点亮WIFI灯
{
	PLC_WIFI_ETH2_(LED_OPEN);
}


//////////////////////////////////本地时间相关转换////////////////////////////////////////
#define IS_LEAP(year) 	((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

static const unsigned short int __mon_yday[2][13] = {
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, //Normal years.
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }  //Leap years.
};

int offset_time(long int t, long int offset, mcu_tm *tp) //本地时间转换
{
    int ret = 1;
    long int days, rem, y;
    const unsigned short int *ip;
    if (NULL == tp) goto end;
    days = t / SECS_PER_DAY;
    rem = t % SECS_PER_DAY;
    rem += offset;
    // compute days according to the given offset
    while (rem < 0) {
        rem += SECS_PER_DAY;
        --days;
    }
    while (rem >= SECS_PER_DAY) {
        rem -= SECS_PER_DAY;
        ++days;
    }
    // calculate hour,min,sec,week day
    tp->tm_hour = rem / SECS_PER_HOUR;
    rem %= SECS_PER_HOUR;
    tp->tm_min = rem / 60;
    tp->tm_sec = rem % 60;
    // calculate year
    y = 1970;
    while (days < 0 || days >= (IS_LEAP(y) ? 366 : 365)) {
        /* Guess a corrected year, assuming 365 days per year.  */
        long int yg = y + days / 365 - (days % 365 < 0);
        /* Adjust DAYS and Y to match the guessed year.  */
        days -= ((yg - y) * 365 + LEAPS_THRU_END_OF(yg - 1) - LEAPS_THRU_END_OF(y - 1));
        y = yg;
    }
    tp->tm_year = y;
    ip = __mon_yday[IS_LEAP(y)];
    for (y = 11; days < (long int) ip[y]; --y) {
        continue;
    }
    days -= ip[y];
    tp->tm_mon = y + 1;
    tp->tm_mday = days + 1;
    ret = 0;
end:
    return ret;
}


/////////////////////////////////////SHA256相关////////////////////////////////////////////
#define ZDBG 0
#define SHFR(x, n) (((x) >> (n)))
#define ROTR(x, n) (((x) >> (n)) | ((x) << ((sizeof(x) << 3) - (n))))
#define ROTL(x, n) (((x) << (n)) | ((x) >> ((sizeof(x) << 3) - (n))))
#define CHX(x, y, z) (((x) &  (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) &  (y)) ^ ( (x) & (z)) ^ ((y) & (z)))
 
#define BSIG0(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define BSIG1(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SSIG0(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
#define SSIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
#define SHA256_BLOCK_SIZE (512/8)
#define SHA256_COVER_SIZE (SHA256_BLOCK_SIZE*2)

static uint32_t k[64] = {
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
 
#if ZDBG 
static int zdump_hex(const uint8_t *data, int size)
{
    int i =0, l =32;
    if(data[0] ==0x21) return 0;
    for(i=0; i<size; i++) {
        if((i%l) ==0) printf("[%02x]",i/l);
        printf("%02x",data[i]);
        if(((i+1)%l) ==0) printf("\n");
    }
    printf("\n");
    return 0;
}
#else
#define zdump_hex(a, b) 
#endif

char *strlowr(char *str) //字符串大写字母转小写
{
    char *orign=str;
    for (; *str!='\0'; str++)	*str = tolower(*str);
    return orign;
}

static int ztransform(const uint8_t *msg, uint32_t *h)
{
    uint32_t w[64];
    uint32_t a0, b1, c2, d3, e4, f5, g6, h7;
    uint32_t t1, t2;
    int i = 0;
    int j = 0;
    for (i=0; i<16; i++) {
        w[i] = msg[j]<<24 | msg[j+1]<<16 | msg[j+2]<<8 | msg[j+3];
        j += 4;
    }
    for(i=16; i<64; i++){
        w[i] = SSIG1(w[i-2])+w[i-7]+SSIG0(w[i-15])+w[i-16];
    }
    zdump_hex((uint8_t*)w, 64*4);
    a0 = h[0];
    b1 = h[1];
    c2 = h[2];
    d3 = h[3];
    e4 = h[4];
    f5 = h[5];
    g6 = h[6];
    h7 = h[7];
    for (i= 0; i<64; i++) {
        t1 = h7 + BSIG1(e4) + CHX(e4, f5, g6) + k[i] + w[i];
        t2 = BSIG0(a0) + MAJ(a0, b1, c2);
        h7 = g6;
        g6 = f5;
        f5 = e4;
        e4 = d3 + t1;
        d3 = c2;
        c2 = b1;
        b1 = a0;
        a0 = t1 + t2;
    }
    h[0] += a0;
    h[1] += b1;
    h[2] += c2;
    h[3] += d3;
    h[4] += e4;
    h[5] += f5;
    h[6] += g6;
    h[7] += h7;
    return 0;
}
 
int zsha256(const uint8_t *src, uint32_t len, uint32_t *hash)
{
    uint8_t *tmp = (uint8_t*)src;
    uint8_t  cover_data[SHA256_COVER_SIZE];
    uint32_t cover_size = 0;
    uint32_t i =0, n =0, m =0;
    uint32_t h[8];
    h[0] = 0x6a09e667;
    h[1] = 0xbb67ae85;
    h[2] = 0x3c6ef372;
    h[3] = 0xa54ff53a;
    h[4] = 0x510e527f;
    h[5] = 0x9b05688c;
    h[6] = 0x1f83d9ab;
    h[7] = 0x5be0cd19;
    memset(cover_data, 0x00, sizeof(uint8_t)*SHA256_COVER_SIZE);
    n = len / SHA256_BLOCK_SIZE;
    m = len % SHA256_BLOCK_SIZE;
    if(m < 56)	cover_size = SHA256_BLOCK_SIZE;
    else 		cover_size = SHA256_BLOCK_SIZE*2;
    if (m != 0) memcpy(cover_data, tmp + (n * SHA256_BLOCK_SIZE), m);
    cover_data[m] = 0x80;
    cover_data[cover_size-4]  = ((len*8)&0xff000000) >> 24;
    cover_data[cover_size-3]  = ((len*8)&0x00ff0000) >> 16;
    cover_data[cover_size-2]  = ((len*8)&0x0000ff00) >> 8;
    cover_data[cover_size-1]  = ((len*8)&0x000000ff);
    zdump_hex(tmp, len-m);
    zdump_hex(cover_data, cover_size);
    for (i=0; i<n; i++) {ztransform(tmp, h); tmp +=SHA256_BLOCK_SIZE;}
    tmp = cover_data;
    n = cover_size/SHA256_BLOCK_SIZE;
    for (i=0; i<n; i++) {ztransform(tmp, h); tmp +=SHA256_BLOCK_SIZE;}
    if(NULL !=hash) memcpy(hash, h, sizeof(uint32_t)*8);
    return 0;
}

int get_sha256(unsigned char *pData,unsigned long iLen,char *pSha256) //获得缓冲区数据的SHA256值,pSha256传入长度65字节
{
	uint32_t sha[8] ={0};
	zsha256(pData,iLen,sha); //计算SHA256
	for(int i=0; i<8; i++) {sprintf(pSha256+i*8,"%08lx",sha[i]);}
	return 64;
}

